﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Unscrambler.ViewModels;
using UnscramblerUnitTests.Mocks;

namespace UnscramblerUnitTests.ViewModels
{
    [TestFixture]
    public class GameViewModelTests
    {
        private GameViewModel _viewModel;
        private MockGameboardViewModel mockGameboardViewModel;

        [SetUp]
        public void SetupTest()
        {
            _viewModel = new GameViewModel();
            mockGameboardViewModel = new MockGameboardViewModel();
        }

        [Test]
        public void TestInitialPropertyStates()
        {
            Assert.IsFalse(_viewModel.IsGameInProgress);
            Assert.IsFalse(_viewModel.ShowHelp);
            Assert.IsFalse(_viewModel.AskIfUserWantsToExitCurrentGame);
            Assert.IsFalse(_viewModel.AskIfUserWantsToRestartCurrentGame);
            
        }

        [Test]
        [ExpectedException(typeof(NullReferenceException))]
        public void TestStartGameWithoutInjectingGameboardViewModel()
        {
            _viewModel.StartGameCommand.Execute(null);
        }

        [Test]
        public void TestStartGame()
        {
            
            _viewModel.GameboardViewModel = mockGameboardViewModel;
            
            Assert.IsFalse(mockGameboardViewModel.StartGameCommandExecuted);
            _viewModel.StartGameCommand.Execute(null);
            Assert.IsTrue(_viewModel.IsGameInProgress);
            Assert.IsTrue(mockGameboardViewModel.StartGameCommandExecuted);
        }

        [Test]
        public void TestStartAlreadyStartedGame()
        {
            TestStartGame();
            _viewModel.StartGameCommand.Execute(null);
            Assert.IsTrue(_viewModel.AskIfUserWantsToRestartCurrentGame);
        }

        [Test]
        public void TestQuitAlreadyStartedGame()
        {
            TestStartGame();
            _viewModel.EndGameCommand.Execute(null);
            Assert.IsTrue(_viewModel.AskIfUserWantsToExitCurrentGame);
        }

        [Test]
        public void TestCancelExitStartedGame()
        {
            TestQuitAlreadyStartedGame();
            _viewModel.CancelStartGameCommand.Execute(null);
            Assert.IsTrue(_viewModel.IsGameInProgress);

        }

        [Test]
        public void TestExitGameThatMightBeRestarted()
        {
            TestStartAlreadyStartedGame();
            _viewModel.EndGameCommand.Execute(null);
            Assert.IsTrue(_viewModel.AskIfUserWantsToExitCurrentGame &&
                _viewModel.AskIfUserWantsToRestartCurrentGame);

        }

        [Test]
        public void TestCancelExitGame()
        {
            this.TestStartGame();
            _viewModel.EndGameCommand.Execute(null);
            Assert.IsTrue(_viewModel.AskIfUserWantsToExitCurrentGame);
            _viewModel.CancelExitGameCommand.Execute(null);
            Assert.IsFalse(_viewModel.AskIfUserWantsToExitCurrentGame);
        }

        [Test]
        public void TestToggleHelp()
        {
            Assert.IsFalse(_viewModel.ShowHelp);
            _viewModel.ToggleHelpCommand.Execute(null);
            Assert.IsTrue(_viewModel.ShowHelp);
            _viewModel.ToggleHelpCommand.Execute(null);
            Assert.IsFalse(_viewModel.ShowHelp);
        }

        [Test]
        public void TestGetHint()
        {
            this.TestStartGame();
            _viewModel.GetHintCommand.Execute(null);
            Assert.IsTrue(mockGameboardViewModel.GetHintCommandExecuted);
        }

        [Test]
        public void TestCantSkipWordWithoutStartingAGame()
        {
            Assert.IsFalse(_viewModel.SkipWordCommand.CanExecute(null));
        }

        [Test]
        public void TestCantSkipWordIfCurrentWordIsCorrect()
        {
            this.TestStartGame();
            mockGameboardViewModel.IsCurrentWordCorrect = true;
            Assert.IsFalse(_viewModel.SkipWordCommand.CanExecute(null));
        }

        [Test]
        public void TestSkipWord()
        {
            this.TestStartGame();
            Assert.IsTrue(_viewModel.SkipWordCommand.CanExecute(null));
            _viewModel.SkipWordCommand.Execute(null);
            Assert.IsTrue(mockGameboardViewModel.SkipWordCommandExecuted);

        }

        [Test]
        public void TestGameOverNotification()
        {
            this.TestStartGame();
            Assert.IsTrue(_viewModel.IsGameInProgress);
            mockGameboardViewModel.ForceGameToEnd();
            Assert.IsFalse(_viewModel.IsGameInProgress);
        }
    }
}
